const jsonServer = require("json-server");
const db = jsonServer.router("./db.json").db;
const Joi = require("joi");
const md5 = require("md5");

const server = jsonServer.create();
const schema = {
  username: Joi.string()
    .pattern(/^[\w]{4,16}$/)
    .required()
    .custom((value, helpers) => {
      const v = db.get("users").find({ username: value }).value();
      if (v) {
        return helpers.error("any.exists");
      }
      return value;
    })
    .messages({
      "any.required": "{{#key}} is required",
      "string.pattern.base": "{{#key}} must be between 4 and 16 characters ",
      "string.empty": "{{#key}} is not allowed to be empty",
      "any.exists": "{{#key}} already exists",
    }),
  password: Joi.string()
    .pattern(/^[\w]{4,16}$/)
    .required()
    .messages({
      "any.required": "{{#key}} is required",
      "string.pattern.base": "{{#key}} must be between 4 and 16 characters",
      "string.empty": "{{#key}} is not allowed to be empty",
    }),
  role: Joi.string().required().messages({
    "any.required": "{{#key}} is required",
    "string.empty": "{{#key}} is not allowed to be empty",
  }),
};

/**
 * POST /users
 * @tags users - 用户管理
 * @summary 添加用户
 * @param {post-users} request.body.required - 用户对象 - application/json
 * @return {object} 200 - success response
 */
server.post("/users", async (req, res, next) => {
  try {
    const { password } = await Joi.object(schema).validateAsync(req.body, {
      abortEarly: false,
    });
    req.body.password = md5(password);
  } catch (error) {
    return res.status(400).send({
      status: 400,
      success: false,
      message: error.details.map((el) => el.message)[0],
    });
  }
  next();
});

/**
 * PATCH /users/{id}
 * @tags users
 * @summary 根据ID编辑用户
 * @param {string} id.path.required - 用户ID
 * @param {patch-users} request.body.required - 用户对象 - application/json
 * @return {object} 200 - success response
 */
server.patch("/users/:id", async (req, res, next) => {
  try {
    const s = Object.entries(schema).filter(([key]) => {
      return ["username", "role"].includes(key);
    });
    await Joi.object(Object.fromEntries(s)).validateAsync(req.body);
    next();
  } catch (error) {
    res.status(400).send({
      status: 400,
      success: false,
      message: error.details?.map((el) => el.message)[0],
    });
  }
});

module.exports = () => server;
